local skynet = require "skynet"
local socket = require "skynet.socket"
local sproto = require "sproto"
local sprotoloader = require "sprotoloader"

local WATCHDOG
local host
local proto_pack
local client_fd
local player_id

local CMD = {}
local REQUEST = {}
local clientReady = false

local function broadcast_package(pack, fd)
	local package = string.pack(">s2", pack)
	skynet.send(WATCHDOG, "lua", "broadcast", package, fd)
end

local function send_package(pack, fd)
	local package = string.pack(">s2", pack)
	socket.write(fd, package)
end

function REQUEST:dead()
	print("player dead", self.id)
	skynet.call("SIMPLEDB", "lua", "dead", self.id)
end

function REQUEST:login()
	skynet.error(">>>> user login:")
	skynet.error(self.name)
	skynet.error(self.password)

	player_id = skynet.call("SIMPLEDB", "lua", "login", self.name, self.password)

	send_package(proto_pack("login", {id=player_id, name=self.name}), client_fd)
	skynet.error(">>>>> db return:"..player_id)
	--无法登陆，密码错误或者已经在线
	if player_id < 0 then
		skynet.send(WATCHDOG, "lua", "close", client_fd)
		return
	end

	local player = skynet.call("SIMPLEDB", "lua", "get_player", player_id)

	--Load in other scenes
	broadcast_package(proto_pack("enter_scene", player), 0)

	--Load other players
	local players = skynet.call("SIMPLEDB", "lua", "get_players")
	
	for i,v in pairs(players) do
		if v.id ~= player_id then
			skynet.error("Load other players=============id: ", v.id)
			send_package(proto_pack("enter_scene", v), client_fd)
		end
	end

	-- if player_id == 0 then
	-- 	send_package(proto_pack("enter_scene", player), client_fd)
	-- end
	-- if player_id == 1 then
	-- 	local player0 = skynet.call("SIMPLEDB", "lua", "get_player", 0)
	-- 	send_package(proto_pack("enter_scene", player0), client_fd)
	-- 	send_package(proto_pack("enter_scene", player), 0)
	-- end

end

function REQUEST:spawn_arrow()

	broadcast_package(proto_pack("spawn_arrow", {id = self.id, posX = self.posX, posY = self.posY, posZ = self.posZ, dirX = self.dirX, dirY = self.dirY, dirZ = self.dirZ, angle = self.angle}), client_fd)
end

function REQUEST:send_sync_arrow()

	broadcast_package(proto_pack("send_sync_arrow", {id = self.id, posX = self.posX, posY = self.posY, posZ = self.posZ, rotX = self.rotX, rotY = self.rotY, rotZ = self.rotZ, rotW = self.rotW}), client_fd)
end

function REQUEST:send_pos()

	broadcast_package(proto_pack("send_pos", {id = self.id, posX = self.posX, posY = self.posY, posZ = self.posZ}), client_fd)
end

function REQUEST:update_arrow()

	broadcast_package(proto_pack("update_arrow", {id = self.id, arrowNum = self.arrowNum}), client_fd)
end

function REQUEST:update_life()

	broadcast_package(proto_pack("update_life", {id = self.id, lifeNum = self.lifeNum}), client_fd)
end

local function request(name, args, response)
	local f = assert(REQUEST[name])
	local r = f(args)
	-- if response then
		-- skynet.error(">>>>>>>>>>> response:"..name)
		-- return response(r)
	-- end
end



skynet.register_protocol {
	name = "client",
	id = skynet.PTYPE_CLIENT,
	unpack = function (msg, sz)
		return host:dispatch(msg, sz)
	end,
	dispatch = function (fd, _, type, ...)
		--assert(fd == client_fd)	-- You can use fd to reply message
		skynet.ignoreret()	-- session is fd, don't call skynet.ret
		--skynet.trace()
		if type == "REQUEST" then
			args = ...
			--skynet.error("=====================")
			--skynet.error(args)
			--skynet.error("=====================")


			local ok, result  = pcall(request, ...)
			if ok then
				if result then
					send_package(result, fd)
				end
			else
				skynet.error(result)
			end
		else
			assert(type == "RESPONSE")
			error "This example doesn't support request client"
		end
	end
}

function CMD.start(conf)
	local fd = conf.client
	local gate = conf.gate
	WATCHDOG = conf.watchdog
	client_fd = fd

	host = sprotoloader.load(1):host "package"
	proto_pack = host:attach(sprotoloader.load(2))

	skynet.call(gate, "lua", "forward", fd)
	print("fd is ------: ", fd)
end

function CMD.disconnect(fd)
	skynet.send("SIMPLEDB", "lua", "logout", player_id)
	local pack = proto_pack("logout", { id = player_id})
	broadcast_package(pack, fd)
	skynet.exit()
end

skynet.start(function()
	skynet.dispatch("lua", function(_,_, command, ...)
		local f = CMD[command]
		skynet.ret(skynet.pack(f(...)))
	end)
end)
